package com.example.musicplayer.service;

import android.animation.Animator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextPaint;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import com.example.musicplayer.ActivityStackManager;
import com.example.musicplayer.DataLoadManager;
import com.example.musicplayer.MusicPlayerApplication;
import com.example.musicplayer.R;
import com.example.musicplayer.adapter.DesktopMusicListAdapter;
import com.example.musicplayer.adapter.DesktopMusicMenuListAdapter;
import com.example.musicplayer.adapter.SlideListViewAdapter;
import com.example.musicplayer.commonUtils.DisplayUtil;
import com.example.musicplayer.musicClass.MusicMenu;
import com.example.musicplayer.musicTools.Lyric;
import com.example.musicplayer.settings.DesktopLyricSettings;
import com.example.musicplayer.settings.MusicPlayerSettings;
import com.example.musicplayer.view.HorizontalListView;
import com.example.musicplayer.view.StrokeTextView;
import com.example.musicplayer.viewTools.ViewAlphaAnimation;
import com.example.musicplayer.viewTools.ViewRotateAnimation;

public class DesktopLyricService extends Service implements View.OnClickListener {
    private static final int CLICK_EVENT_MIN_DELTA = 5;
    private static final int DISPLAY_VIEW_ALL_TIME = 5 * 1000;
    private static final int INVALID_LOC_Y = -1;
    private final DesktopLyricBinder mBinder = new DesktopLyricBinder();
    private MusicService.MusicBinder mMusicBinder;
    private WindowManager mManager;
    private WindowManager.LayoutParams mParams;
    private DesktopLyricSettings mLyricSettings;
    private View mView;
    private View mViewAll;
    private TextView mFirstLyric;
    private TextView mSecondLyric;
    private ListView mListView;
    private HorizontalListView mMusicMenuListView;
    private SeekBar mAlphaBar;
    private SeekBar mRedBar;
    private SeekBar mGreenBar;
    private SeekBar mBlueBar;
    private DesktopMusicMenuListAdapter mMusicMenuListAdapter;
    private DesktopMusicListAdapter mMusicListAdapter;
    private int mHeightMax;
    private int mHeightMusicList;
    private int mHeightMusicListExpand;
    private int mTopMargin;
    private int mCurrentY;
    //record the locked location
    private int mLockY = INVALID_LOC_Y;
    private int mMaxY;
    //if display all information
    private boolean mDisplayViewAll = false;
    private boolean mDisplayMusicList = false;
    private boolean mMusicListExpand = false;
    private boolean mViewAdded = false;
    //if view all will hide after seconds
    private boolean mViewAllPinned = false;
    //record the selected color image view id
    private int mSelectedColorId;
    private int mCurrentLyricPosition;

    private final Handler mHandler = new Handler();
    private final Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            if (mDisplayViewAll && !mViewAllPinned && !mDisplayMusicList) {
                changeDisplayViewAll();
            }
        }
    };

    private final Runnable mLyricRunnable = new Runnable() {
        private int mCurrentPosition = 0;

        @Override
        public void run() {
            if (mMusicBinder != null) {
                int currentTime = mMusicBinder.getCurrent();
                int currentPosition;
                if (currentTime >= Lyric.getStartTime(mCurrentPosition)) {
                    currentPosition = mCurrentPosition;
                } else {
                    currentPosition = 0;
                }
                for (; currentPosition < Lyric.getSize(); currentPosition++) {
                    if (currentTime >= Lyric.getStartTime(currentPosition) &&
                            currentTime < Lyric.getStartTime(currentPosition + 1)) {
                        break;
                    }
                }
                mCurrentPosition = currentPosition;
                updateLyric(Lyric.getLyric(currentPosition), Lyric.getLyric(currentPosition + 1), mCurrentPosition);
                if (mMusicBinder.isPlaying()) {
                    mHandler.postDelayed(mLyricRunnable, getResources().getInteger(R.integer.refresh_time));
                }
            }
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        mParams = new WindowManager.LayoutParams();
        mLyricSettings = new DesktopLyricSettings(DataLoadManager.getInstance());
        createView();
        addListener();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacks(mRunnable);
        mHandler.removeCallbacks(mLyricRunnable);
        showDesktopLyric(false);
        mManager = null;
        mParams = null;
    }

    @SuppressLint("InflateParams")
    private void createView() {
        mHeightMax = (int) getResources().getDimension(R.dimen.desktop_lyric_view_height_max);
        mHeightMusicList = (int) getResources().getDimension(R.dimen.desktop_lyric_music_list_height);
        mHeightMusicListExpand = (int) getResources().getDimension(R.dimen.desktop_lyric_music_list_expand_height);
        mTopMargin = (int) getResources().getDimension(R.dimen.desktop_lyric_view_top_margin);
        mView = LayoutInflater.from(this).inflate(R.layout.desktop_lyric_view, null);
        mViewAll = mView.findViewById(R.id.desktop_lyric_view_all);
        mFirstLyric = mView.findViewById(R.id.first_lyric);
        mSecondLyric = mView.findViewById(R.id.second_lyric);
        mListView = mView.findViewById(R.id.desktop_lyric_list_view);
        mAlphaBar = mView.findViewById(R.id.seekbar_alpha);
        mRedBar = mView.findViewById(R.id.seekbar_red);
        mGreenBar = mView.findViewById(R.id.seekbar_green);
        mBlueBar = mView.findViewById(R.id.seekbar_blue);
        //set background for current view
        mViewAll.setBackgroundColor(mLyricSettings.getBackgroundColor());
        //set text style and set stroke width
        TextPaint paint = mFirstLyric.getPaint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(1.5f);
        paint = mSecondLyric.getPaint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(1.5f);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        } else {
            mParams.type = WindowManager.LayoutParams.TYPE_PHONE;
        }
        mParams.format = PixelFormat.RGBA_8888;
        int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
        if (MusicPlayerSettings.isDesktopLyricLock()) {
            flags = flags | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
        }
        mParams.flags = flags;
        mParams.width = WindowManager.LayoutParams.MATCH_PARENT;
        mParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mParams.gravity = Gravity.TOP;
        //get the location last exit this service
        mParams.x = 0;
        mCurrentY = mParams.y = writeOrReadLocY(false);
        updateMaxY();
        updateLyricSizeAndColor();
        showDesktopLyric(true);
    }

    @SuppressLint("ClickableViewAccessibility")
    private void addListener() {
        if (mView != null) {
            mFirstLyric.setOnClickListener(this);
            mSecondLyric.setOnClickListener(this);
            mView.findViewById(R.id.imageview_main_icon).setOnClickListener(this);
            mView.findViewById(R.id.imageview_lock).setOnClickListener(this);
            mView.findViewById(R.id.imageview_close).setOnClickListener(this);
            mView.findViewById(R.id.imageview_set).setOnClickListener(this);
            mView.findViewById(R.id.imageview_play_mode).setOnClickListener(this);
            mView.findViewById(R.id.imageview_last).setOnClickListener(this);
            mView.findViewById(R.id.imageview_play).setOnClickListener(this);
            mView.findViewById(R.id.imageview_pause).setOnClickListener(this);
            mView.findViewById(R.id.imageview_next).setOnClickListener(this);
            mView.findViewById(R.id.imageview_favorite).setOnClickListener(this);
            mView.findViewById(R.id.imageview_music_list).setOnClickListener(this);
            mView.findViewById(R.id.imageview_pin_area).setOnClickListener(this);
            mView.findViewById(R.id.imageview_top).setOnClickListener(this);
            mView.findViewById(R.id.imageview_bottom).setOnClickListener(this);
            mView.findViewById(R.id.imageview_locate).setOnClickListener(this);
            mView.findViewById(R.id.imageview_expand).setOnClickListener(this);
            mView.findViewById(R.id.imageview_music_menu).setOnClickListener(this);
            mView.findViewById(R.id.imageview_set_background).setOnClickListener(this);
            mView.findViewById(R.id.background_set_default).setOnClickListener(this);
            mView.findViewById(R.id.font_increase).setOnClickListener(this);
            mView.findViewById(R.id.font_decrease).setOnClickListener(this);
            mView.findViewById(R.id.color_check_1).setOnClickListener(this);
            mView.findViewById(R.id.color_check_2).setOnClickListener(this);
            mView.findViewById(R.id.color_check_3).setOnClickListener(this);
            mView.findViewById(R.id.color_check_4).setOnClickListener(this);
            mView.findViewById(R.id.color_check_5).setOnClickListener(this);
            mView.findViewById(R.id.desktop_collapse_area).setOnClickListener(this);
            mViewAll.setOnClickListener(this);
        }
        //add touch listen that can move this view
        DesktopLyricTouchListener touchListener = new DesktopLyricTouchListener();
        mFirstLyric.setOnTouchListener(touchListener);
        mSecondLyric.setOnTouchListener(touchListener);
        mViewAll.setOnTouchListener(touchListener);
    }

    private void initMusicList() {
        mMusicListAdapter = new DesktopMusicListAdapter(mListView, mMusicBinder, mLyricSettings, this);
        mListView.setAdapter(mMusicListAdapter);
        mListView.post(new Runnable() {
            @Override
            public void run() {
                if (mListView != null && mMusicBinder != null)
                    mListView.setSelection(mMusicBinder.getNowMusicPosition());
            }
        });
        mMusicListAdapter.setOnItemClickListener(new SlideListViewAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View parent, View view, int position, long id) {
                if (mMusicBinder != null) {
                    if (position != mMusicBinder.getNowMusicPosition()) {
                        mMusicBinder.start(position);
                    } else if (!mMusicBinder.isPlaying()) {
                        mMusicBinder.start();
                    }
                }
            }
        });
    }

    private void showDesktopLyric(boolean show) {
        if (mManager != null) {
            if (show && !mViewAdded && mMusicBinder != null && mMusicBinder.hasMusic() &&
                    (!MusicPlayerApplication.getInstance().isForeground() || MusicPlayerSettings.isDesktopLyricInApp())) {
                mManager.addView(mView, mParams);
                mViewAdded = true;
            }
            if (!show && mViewAdded) {
                mManager.removeView(mView);
                mViewAdded = false;
            }
        }
    }

    private void showMusicList(boolean show) {
        mView.findViewById(R.id.desktop_lyric_view_list).setVisibility(show ?
                View.VISIBLE : View.GONE);
        mDisplayMusicList = show;
        updateMaxY();
        if (show && mMusicListAdapter != null) {
            mMusicListAdapter.notifyDataSetChanged();
        }
    }

    private void expandMusicList(boolean expand) {
        if (mDisplayMusicList) {
            View musicListView = mView.findViewById(R.id.desktop_lyric_view_list);
            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) musicListView.getLayoutParams();
            lp.height = expand ? mHeightMusicListExpand : mHeightMusicList;
            musicListView.setLayoutParams(lp);
            //mView.findViewById(R.id.imageview_expand).setRotation(expand ? 180f : 0f);
            mView.findViewById(R.id.music_list_expand_view).setVisibility(expand ? View.VISIBLE : View.GONE);
            mView.findViewById(R.id.music_menu_list_view).setVisibility(expand ? View.VISIBLE : View.GONE);
            mView.findViewById(R.id.background_set_view).setVisibility(View.GONE);
            mView.findViewById(R.id.imageview_music_menu).setVisibility(expand ? View.VISIBLE : View.GONE);
            mView.findViewById(R.id.imageview_set_background).setVisibility(expand ? View.VISIBLE : View.GONE);
            mMusicListExpand = expand;
            updateMaxY();
            setupMusicMenuList(expand);
            if (expand) {
                setupBackgroundSetView();
            }
        }
    }

    private void updateViewLoc() {
        if (mViewAdded) {
            mCurrentY = Math.max(mCurrentY, 0);
            mCurrentY = Math.min(mCurrentY, mMaxY);
            if (!mDisplayViewAll) {
                mLockY = mCurrentY;
            }
            mParams.y = mCurrentY;
            mManager.updateViewLayout(mView, mParams);
        }
    }

    //update the max y location in screen
    private void updateMaxY() {
        Activity activity = ActivityStackManager.getInstance().getTopActivity();
        if (activity != null) {
            //mMaxY = DisplayUtil.getRealScreenSize(activity)[1] - DisplayUtil.getStatusBarHeight(getResources());
            mMaxY = DisplayUtil.getRealScreenSize(activity)[1];
            if (mDisplayViewAll) {
                mMaxY -= mHeightMax;
                if (mDisplayMusicList) {
                    mMaxY -= mMusicListExpand ? mHeightMusicListExpand : mHeightMusicList;
                }
            } else {
                int lyricHeight = mView.findViewById(R.id.desktop_lyric_area).getHeight();
                mMaxY = mMaxY - lyricHeight - mTopMargin;
            }
        }
    }

    private void updateLyric(String currentLyric, String nextLyric, int lyricPosition) {
        TextView firstLyric = mView.findViewById(R.id.first_lyric_1);
        TextView secondLyric = mView.findViewById(R.id.second_lyric_1);
        mCurrentLyricPosition = lyricPosition;
        int color = mLyricSettings.getLyricTextColor();
        if (lyricPosition % 2 == 0) {
            mFirstLyric.setText(currentLyric);
            firstLyric.setText(currentLyric);
            firstLyric.setTextColor(color);
            mSecondLyric.setText(nextLyric);
            secondLyric.setText(nextLyric);
            secondLyric.setTextColor(getResources().getColor(R.color.white));
        } else {
            mFirstLyric.setText(nextLyric);
            firstLyric.setText(nextLyric);
            firstLyric.setTextColor(getResources().getColor(R.color.white));
            mSecondLyric.setText(currentLyric);
            secondLyric.setText(currentLyric);
            secondLyric.setTextColor(color);
        }
    }

    private void updateLyricSizeAndColor() {
        TextView firstLyric = mView.findViewById(R.id.first_lyric_1);
        TextView secondLyric = mView.findViewById(R.id.second_lyric_1);
        //update size
        float textSize = mLyricSettings.getLyricTextSize();
        mFirstLyric.setTextSize(textSize);
        firstLyric.setTextSize(textSize);
        mSecondLyric.setTextSize(textSize);
        secondLyric.setTextSize(textSize);
        //update color
        int color = mLyricSettings.getLyricTextColor();
        if (mCurrentLyricPosition % 2 == 0) {
            firstLyric.setTextColor(color);
        } else {
            secondLyric.setTextColor(color);
        }
        ((ImageView) mView.findViewById(R.id.imageview_collapse)).setColorFilter(color);
    }

    @SuppressLint("NonConstantResourceId")
    private int getLyricColorById(int id) {
        switch (id) {
            case R.id.color_check_2:
                return DesktopLyricSettings.LYRIC_COLOR_2;
            case R.id.color_check_3:
                return DesktopLyricSettings.LYRIC_COLOR_3;
            case R.id.color_check_4:
                return DesktopLyricSettings.LYRIC_COLOR_4;
            case R.id.color_check_5:
                return DesktopLyricSettings.LYRIC_COLOR_5;
            case R.id.color_check_1:
            default:
                return DesktopLyricSettings.LYRIC_COLOR_1;
        }
    }

    private int getIdByLyricColor(int lyricColor) {
        switch (lyricColor) {
            case DesktopLyricSettings.LYRIC_COLOR_2:
                return R.id.color_check_2;
            case DesktopLyricSettings.LYRIC_COLOR_3:
                return R.id.color_check_3;
            case DesktopLyricSettings.LYRIC_COLOR_4:
                return R.id.color_check_4;
            case DesktopLyricSettings.LYRIC_COLOR_5:
                return R.id.color_check_5;
            case DesktopLyricSettings.LYRIC_COLOR_1:
            default:
                return R.id.color_check_1;
        }
    }

    private void updateFavorite(boolean isFavorite) {
        if (isFavorite) {
            ((ImageView) mView.findViewById(R.id.imageview_favorite)).setImageResource(R.drawable.icon_desktop_favorite);
        } else {
            ((ImageView) mView.findViewById(R.id.imageview_favorite)).setImageResource(R.drawable.icon_desktop_not_favorite);
        }
    }

    private void updatePlayState(boolean isPlaying) {
        if (isPlaying) {
            mView.findViewById(R.id.imageview_play).setVisibility(View.GONE);
            mView.findViewById(R.id.imageview_pause).setVisibility(View.VISIBLE);
        } else {
            mView.findViewById(R.id.imageview_play).setVisibility(View.VISIBLE);
            mView.findViewById(R.id.imageview_pause).setVisibility(View.GONE);
        }
    }

    private void updatePlayMode() {
        int imageId;
        switch (mMusicBinder.getMode()) {
            case REPEAT:
                imageId = R.drawable.icon_desktop_repeat;
                break;
            case REPEAT_ONE:
                imageId = R.drawable.icon_desktop_repeat_one;
                break;
            case RANDOM:
            default:
                imageId = R.drawable.icon_desktop_random;
                break;
        }
        ((ImageView) mView.findViewById(R.id.imageview_play_mode)).setImageResource(imageId);
    }

    private void updateLockState(boolean isLocked) {
        if (isLocked) {
            if (mDisplayViewAll) {
                changeDisplayViewAll();
            }
            mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
        } else {
            mParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
        }
        updateViewLoc();
    }

    //change the display state of mViewAll
    private void changeDisplayViewAll() {
        if (mDisplayViewAll) {
            mViewAll.setVisibility(View.GONE);
            mDisplayViewAll = false;
            showMusicList(false);
        } else {
            mViewAll.setVisibility(View.VISIBLE);
            mDisplayViewAll = true;
        }
        updateMaxY();
        if (!mDisplayViewAll) {
            if (mLockY != INVALID_LOC_Y) {
                mCurrentY = mLockY;
            }
            updateViewLoc();
            mHandler.removeCallbacks(mRunnable);
        } else {
            mHandler.postDelayed(mRunnable, DISPLAY_VIEW_ALL_TIME);
        }
    }

    private void setupMusicMenuList(boolean visible) {
        if (visible) {
            mMusicMenuListView = mView.findViewById(R.id.music_menu_list_view);
            mMusicMenuListAdapter = new DesktopMusicMenuListAdapter(this, mMusicBinder, mLyricSettings);
            mMusicMenuListView.setAdapter(mMusicMenuListAdapter);
            mMusicMenuListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    if (mMusicBinder != null) {
                        mMusicMenuListAdapter.playMusicMenu(position);
                    }
                }
            });
            /*//long press to start the music menu details activity
            mMusicMenuListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
                @Override
                public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                    Object obj = mMusicMenuListAdapter.getItem(position);
                    if (obj instanceof MusicMenu) {
                        Intent intent = new Intent(DesktopLyricService.this, MusicMenuDisplayActivity.class);
                        intent.putExtra("musicMenuName", ((MusicMenu) obj).getName());
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                    }
                    return true;
                }
            });*/
        } else {
            mMusicMenuListView = null;
            mMusicMenuListAdapter = null;
        }
    }

    private void setupBackgroundSetView() {
        int backgroundColor = mLyricSettings.getBackgroundColor();
        mAlphaBar.setMax(255);
        mRedBar.setMax(255);
        mGreenBar.setMax(255);
        mBlueBar.setMax(255);
        mAlphaBar.setProgress(Color.alpha(backgroundColor));
        mRedBar.setProgress(Color.red(backgroundColor));
        mGreenBar.setProgress(Color.green(backgroundColor));
        mBlueBar.setProgress(Color.blue(backgroundColor));
        updateBackgroundSetInfo();
        //add listener
        mAlphaBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                updateBackgroundColor(false);
                updateBackgroundSetInfo();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                updateBackgroundColor(true);
            }
        });
        mRedBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                updateBackgroundColor(false);
                updateBackgroundSetInfo();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                updateBackgroundColor(true);
            }
        });
        mGreenBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                updateBackgroundColor(false);
                updateBackgroundSetInfo();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                updateBackgroundColor(true);
            }
        });
        mBlueBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                updateBackgroundColor(false);
                updateBackgroundSetInfo();
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                updateBackgroundColor(true);
            }
        });
    }

    private void updateBackgroundColor(boolean saveChange) {
        int color = Color.argb(mAlphaBar.getProgress(), mRedBar.getProgress(), mGreenBar.getProgress()
                , mBlueBar.getProgress());
        mViewAll.setBackgroundColor(color);
        if (saveChange) {
            mLyricSettings.changeBackgroundColor(color);
        }
    }

    @SuppressLint("SetTextI18n")
    private void updateBackgroundSetInfo() {
        if (mView != null) {
            ((StrokeTextView) mView.findViewById(R.id.text_alpha)).setText(mAlphaBar.getProgress() + "");
            ((StrokeTextView) mView.findViewById(R.id.text_red)).setText(mRedBar.getProgress() + "");
            ((StrokeTextView) mView.findViewById(R.id.text_green)).setText(mGreenBar.getProgress() + "");
            ((StrokeTextView) mView.findViewById(R.id.text_blue)).setText(mBlueBar.getProgress() + "");
        }
    }

    public int writeOrReadLocY(boolean isWrite) {
        DataLoadManager dataLoadManager = DataLoadManager.getInstance();
        if (dataLoadManager != null) {
            if (isWrite) {
                dataLoadManager.writeOneBaseData(DataLoadManager.DESKTOP_LYRIC_VIEW_LOC_Y, mCurrentY);
            } else {
                return dataLoadManager.readOneBaseData(DataLoadManager.DESKTOP_LYRIC_VIEW_LOC_Y, 0);
            }
        }
        return 0;
    }

    @SuppressLint("NonConstantResourceId")
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imageview_main_icon:
                Activity activity = ActivityStackManager.getInstance().getTopActivity();
                if (activity != null) {
                    Intent intent = new Intent(this, activity.getClass());
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    startActivity(intent);
                }
                break;
            case R.id.imageview_lock:
                MusicPlayerSettings.setDesktopLyricLock(true);
                sendBroadcast(new Intent(getString(R.string.broadcast_desktop_lyric_lock)));
                break;
            case R.id.imageview_close:
                MusicPlayerSettings.setDesktopLyric(false);
                sendBroadcast(new Intent(getString(R.string.broadcast_desktop_lyric)));
                break;
            case R.id.imageview_set:
                mView.findViewById(R.id.desktop_collapse_area).setVisibility(View.VISIBLE);
                ViewAlphaAnimation animation = new ViewAlphaAnimation();
                animation.appear(mView.findViewById(R.id.desktop_lyric_size_and_color_area));
                animation.disappear(mView.findViewById(R.id.desktop_lyric_control_area));
                break;
            case R.id.imageview_play_mode:
                mMusicBinder.changeMode();
                break;
            case R.id.desktop_collapse_area:
                mView.findViewById(R.id.desktop_collapse_area).setVisibility(View.GONE);
                ViewAlphaAnimation animation_1 = new ViewAlphaAnimation();
                animation_1.disappear(mView.findViewById(R.id.desktop_lyric_size_and_color_area));
                animation_1.appear(mView.findViewById(R.id.desktop_lyric_control_area));
                break;
            case R.id.imageview_last:
                mMusicBinder.startLast();
                break;
            case R.id.imageview_next:
                mMusicBinder.startNext();
                break;
            case R.id.imageview_play:
            case R.id.imageview_pause:
                mMusicBinder.changePlayingState();
                break;
            case R.id.imageview_favorite:
                mMusicBinder.changeMusicFavorite();
                break;
            case R.id.imageview_music_list:
                showMusicList(!mDisplayMusicList);
                break;
            case R.id.imageview_top:
                mListView.smoothScrollToPositionFromTop(0, 0, 100);
                break;
            case R.id.imageview_bottom:
                mListView.smoothScrollToPositionFromTop(mMusicBinder.getMusicCounts() - 1, 0, 100);
                break;
            case R.id.imageview_locate:
                mListView.smoothScrollToPositionFromTop(mMusicBinder.getNowMusicPosition(), 0, 100);
                break;
            case R.id.imageview_expand:
                expandMusicList(!mMusicListExpand);
                ViewRotateAnimation animation_expand = new ViewRotateAnimation(v, ViewRotateAnimation.ROTATION_Z,
                        mMusicListExpand ? 0 : 180, mMusicListExpand ? 180 : 360);
                animation_expand.setPivotX(v.getWidth() / 2);
                animation_expand.setPivotY(v.getHeight() / 2);
                animation_expand.setDuration(300);
                animation_expand.start();
                animation_expand.setAnimationEndListener(animation1 -> {
                    if (mMusicListExpand && mMusicMenuListView != null) {
                        mMusicMenuListView.post(new Runnable() {
                            @Override
                            public void run() {
                                //get the first display position
                                MusicMenu musicMenu = mMusicBinder.getPlayingMusicMenu();
                                if (musicMenu != null) {
                                    mMusicMenuListView.setSelection(musicMenu.getOrder() + 1);
                                }
                            }
                        });
                    }
                });
                break;
            case R.id.imageview_music_menu:
                mView.findViewById(R.id.music_menu_list_view).setVisibility(View.VISIBLE);
                mView.findViewById(R.id.background_set_view).setVisibility(View.GONE);
                break;
            case R.id.imageview_set_background:
                mView.findViewById(R.id.music_menu_list_view).setVisibility(View.GONE);
                mView.findViewById(R.id.background_set_view).setVisibility(View.VISIBLE);
                break;
            case R.id.background_set_default:
                int color = getResources().getColor(R.color.desktop_lyric_background);
                mAlphaBar.setProgress(Color.alpha(color));
                mRedBar.setProgress(Color.red(color));
                mGreenBar.setProgress(Color.green(color));
                mBlueBar.setProgress(Color.blue(color));
                updateBackgroundColor(true);
                break;
            case R.id.imageview_pin_area:
                mViewAllPinned = !mViewAllPinned;
                mView.findViewById(R.id.imageview_pin).setSelected(mViewAllPinned);
                break;
            case R.id.desktop_lyric_view_all:
            case R.id.first_lyric:
            case R.id.second_lyric:
                changeDisplayViewAll();
                break;
            case R.id.font_increase:
                mLyricSettings.changeLyricSize(true);
                updateLyricSizeAndColor();
                updateMaxY();
                break;
            case R.id.font_decrease:
                mLyricSettings.changeLyricSize(false);
                updateLyricSizeAndColor();
                updateMaxY();
                break;
            case R.id.color_check_1:
            case R.id.color_check_2:
            case R.id.color_check_3:
            case R.id.color_check_4:
            case R.id.color_check_5:
                if (mSelectedColorId != v.getId()) {
                    mLyricSettings.changeLyricColor(getLyricColorById(v.getId()));
                    updateLyricSizeAndColor();
                    v.setSelected(true);
                    mView.findViewById(mSelectedColorId).setSelected(false);
                    mSelectedColorId = v.getId();
                    //update music list color
                    if (mMusicListAdapter != null) {
                        mMusicListAdapter.notifyDataSetChanged();
                    }
                    if (mMusicMenuListAdapter != null) {
                        mMusicMenuListAdapter.notifyDataSetChanged();
                    }
                }
                break;
            default:
                break;
        }
        //reset timing
        if (mDisplayViewAll && !mViewAllPinned && !mDisplayMusicList) {
            mHandler.removeCallbacks(mRunnable);
            mHandler.postDelayed(mRunnable, DISPLAY_VIEW_ALL_TIME);
        }
    }

    private class DesktopLyricTouchListener implements View.OnTouchListener {
        private int mStartTouchY;
        private int mStartLayoutY;
        private int mStartRelativeX;
        private int mStartRelativeY;
        //if should execute click event
        private boolean mShouldPerformClick = true;

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            int y = (int) event.getRawY();
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    //do not let it hide
                    mHandler.removeCallbacks(mRunnable);
                    //adjust mCurrentY
                    updateViewLoc();
                    mStartTouchY = y;
                    mStartLayoutY = mCurrentY;
                    mStartRelativeX = (int) event.getX();
                    mStartRelativeY = (int) event.getY();
                    mShouldPerformClick = true;
                    break;
                case MotionEvent.ACTION_MOVE:
                    if (mShouldPerformClick) {
                        int relativeX = (int) event.getX();
                        int relativeY = (int) event.getY();
                        mShouldPerformClick = relativeX >= 0 && relativeX <= v.getMeasuredWidth()
                                && relativeY >= 0 && relativeY <= v.getMeasuredHeight()
                                && Math.abs(relativeX - mStartRelativeX) <= CLICK_EVENT_MIN_DELTA
                                && Math.abs(relativeY - mStartRelativeY) <= CLICK_EVENT_MIN_DELTA;
                    }
                    if (!mShouldPerformClick) {
                        int dy = y - mStartTouchY;
                        mCurrentY = mStartLayoutY + dy;
                        updateViewLoc();
                        if (mDisplayViewAll) {
                            mLockY = INVALID_LOC_Y;
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (mShouldPerformClick) {
                        v.performClick();
                    }
                    if (mDisplayViewAll) {
                        mHandler.postDelayed(mRunnable, DISPLAY_VIEW_ALL_TIME);
                    }
                    writeOrReadLocY(true);
                    break;
                case MotionEvent.ACTION_CANCEL:
                    if (mDisplayViewAll) {
                        mHandler.postDelayed(mRunnable, DISPLAY_VIEW_ALL_TIME);
                    }
                    writeOrReadLocY(true);
                    break;
            }
            return true;
        }
    }

    public class DesktopLyricBinder extends Binder {

        public void setMusicBinder(MusicService.MusicBinder musicBinder) {
            mMusicBinder = musicBinder;
            showDesktopLyric(true);
            mHandler.post(mLyricRunnable);
            //update the layout and view
            updatePlayState(mMusicBinder.isPlaying());
            updateFavorite(mMusicBinder.getMusicFavorite() == 1);
            updatePlayMode();
            mSelectedColorId = getIdByLyricColor(mLyricSettings.getLyricColor());
            mView.findViewById(mSelectedColorId).setSelected(true);
            initMusicList();
        }

        public void showDesktopLyricView(boolean show) {
            if (show) {
                mDisplayViewAll = false;
                mViewAll.setVisibility(View.GONE);
                showMusicList(false);
            } else {
                mHandler.removeCallbacks(mRunnable);
            }
            showDesktopLyric(show);
        }

        public void onLockStateChanged(boolean isLocked) {
            updateLockState(isLocked);
        }

        public void onMusicCompletion() {
            mHandler.removeCallbacks(mLyricRunnable);
            updateLyric("", "", 0);
        }

        public void onMusicPrepared() {
            if (!mViewAdded) {
                showDesktopLyricView(true);
            }
            mHandler.post(mLyricRunnable);
            updateFavorite(mMusicBinder.getMusicFavorite() == 1);
            //update music list
            mMusicListAdapter.notifyDataSetChanged();
            if (mMusicMenuListAdapter != null) {
                mMusicMenuListAdapter.notifyDataSetChanged();
            }
            mListView.smoothScrollToPositionFromTop(mMusicBinder.getNowMusicPosition(), 0, 100);
        }

        public void onPlayListEmpty() {
            showDesktopLyricView(false);
        }

        public void onMusicFavoriteChanged(boolean isFavorite) {
            updateFavorite(isFavorite);
        }

        public void onPlayStateChanged(boolean isPlaying) {
            if (isPlaying) {
                mHandler.post(mLyricRunnable);
            } else {
                mHandler.removeCallbacks(mLyricRunnable);
            }
            updatePlayState(isPlaying);
        }

        public void onPlayModeChanged() {
            updatePlayMode();
        }
    }
}